home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.orig.lzh / rna / maketime.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  9KB  |  458 lines

  1. /*
  2.  * long
  3.  * maketime(argc, argv, type)
  4.  *
  5.  * A standard routine to convert a future time (in English) to seconds.
  6.  * Arguments are order-independent (except for suffixes), and words
  7.  * may be shortened to a non-ambiguous abbreviation.
  8.  * As the time must be in the future, unspecified years, months and days defaul
  9.  
  10.  * to the "next" year, month or day if necessary; otherwise the current
  11.  * month, day and hour are used.
  12.  *
  13.  * type is either TIMES in which days, times are recognised, or just DAYS.
  14.  *
  15.  * Tries hard to give meaningful messages, and make sure the user
  16.  * gets the time she/he wanted!
  17.  *
  18.  * Return is in seconds or 0 if error.
  19.  * Error messages to stderr.
  20.  *
  21.  * Michael Rourke (UNSW) Christmas 1982
  22.  *
  23.  * Syntax:
  24.  *
  25.  *    timespec ::= { time | day | month | year } .
  26.  *    
  27.  *    time ::= [ hour [ ":" min [ ":" second ] ] ] [ timemodifier ] .
  28.  *    
  29.  *    timemodifier ::= "am" | "pm" | "noon" | "midday" | "midnight" | "now" .
  30.  *    
  31.  *    day ::= ( dayofweek [ "week" ] ) | number .
  32.  *    
  33.  *    dayofweek ::= "sunday" | "monday" | "tuesday" | "wednesday" |
  34.  *              "thursday" | "friday" | "saturday" | "tomorrow" |
  35.  *              "today" .
  36.  *    
  37.  *    month ::= "january" | "february" | "march" | "april" | "may" | "june" |
  38.  *          "july" | "august" | "september" | "october" | "november" |
  39.  *          "december" .
  40.  *    
  41.  *    year ::= "19" number .
  42.  *
  43.  */
  44.  
  45. #include "defs.h"
  46.  
  47. #define    NOW     -1
  48.  
  49. static timemod(), noonmid(), daymod(), weekday(), smonth();
  50.  
  51. static struct slist {
  52.     char *s_name;
  53.     int (*s_action)();
  54.     char s_val;
  55.     char s_type;
  56. } slist[] = 
  57. {
  58.     { "am",         timemod,     0,     TIMES,      },
  59.     { "pm",         timemod,     12,     TIMES,      },
  60.     { "noon",         noonmid,     12,     TIMES,      },
  61.     { "midday",     noonmid,     12,     TIMES,      },
  62.     { "midnight",     noonmid,     0,     TIMES,      },
  63.     { "now",         noonmid,     NOW,     TIMES,      },
  64.     { "week",         daymod,         0,     DAYS,      },
  65.     { "sunday",     weekday,     0,     DAYS,      },
  66.     { "monday",     weekday,     1,     DAYS,      },
  67.     { "tuesday",     weekday,     2,     DAYS,      },
  68.     { "wednesday",     weekday,     3,     DAYS,      },
  69.     { "thursday",     weekday,     4,     DAYS,      },
  70.     { "friday",     weekday,     5,     DAYS,      },
  71.     { "saturday",     weekday,     6,     DAYS,      },
  72.     { "tomorrow",     weekday,     7,     DAYS,      },
  73.     { "today",     weekday,     8,     DAYS,      },
  74.     { "january",     smonth,         0,     DAYS,      },
  75.     { "february",     smonth,         1,     DAYS,      },
  76.     { "march",     smonth,         2,     DAYS,      },
  77.     { "april",     smonth,         3,     DAYS,      },
  78.     { "may",         smonth,         4,     DAYS,      },
  79.     { "june",         smonth,         5,     DAYS,      },
  80.     { "july",         smonth,         6,     DAYS,      },
  81.     { "august",     smonth,         7,     DAYS,      },
  82.     { "september",     smonth,         8,     DAYS,      },
  83.     { "october",     smonth,         9,     DAYS,      },
  84.     { "november",     smonth,         10,     DAYS,      },
  85.     { "december",     smonth,         11,     DAYS,      },
  86.     { "",         0,         0,     0,      }
  87. };
  88.  
  89.  
  90. static char daysinmonth[12] = 
  91. {
  92.     31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  93. };
  94.  
  95.  
  96. static int hour, minute, second, day, year, dayofweek, month;
  97. static int settime, setday, setyear, setdayofweek, setmonth;
  98. static int setweek, err, setmod;
  99. static char *curarg;
  100. static struct tm *tim;
  101. static int gtype;        /* global `type' arg */
  102. static short silent;
  103.  
  104. long
  105. maketime(argc, argv, type)
  106. int argc;
  107. char **argv;
  108. int type;
  109. {
  110.     struct tm *localtime();
  111.     long time(), construct(), now, then;
  112.  
  113.     if (type == STIMES)
  114.         type = TIMES, silent = 1;
  115.     else
  116.         silent = 0;
  117.     gtype = type;
  118.     now = time((long *) 0);
  119.     tim = localtime(&now);
  120.  
  121.     /*
  122.      * set defaults 
  123.      */
  124.     hour = tim->tm_hour;
  125.     minute = tim->tm_min;
  126.     second = tim->tm_sec;
  127.     day = tim->tm_mday;
  128.     year = tim->tm_year + 1900;
  129.     dayofweek = tim->tm_wday;
  130.     month = tim->tm_mon;
  131.  
  132.     settime = setday = setyear = setdayofweek = setmonth = 0;
  133.     setweek = err = setmod = 0;
  134.  
  135.     while (argc--)
  136.         timearg(curarg = *argv++);
  137.     if (err)
  138.         return (long) 0;
  139.  
  140.     checktime();
  141.     if (err)
  142.         return (long) 0;
  143.  
  144.     then = construct();
  145.     /*
  146.     if(now > then)
  147.     {
  148.         error("Time specified has passed.");
  149.         return (long) 0;
  150.     }
  151. */
  152.     return then;
  153. }
  154.  
  155.  
  156. static
  157. timearg(s)
  158. char *s;
  159. {
  160.     lower(s);
  161.     if (isdigit(*s))
  162.         numbers(s);
  163.     else
  164.         words(s);
  165. }
  166.  
  167.  
  168. static
  169. lower(s)
  170. register char *s;
  171. {
  172.     while (*s) {
  173.         *s = tolower(*s);
  174.         s++;
  175.     }
  176. }
  177.  
  178.  
  179. static
  180. numbers(s)
  181. register char *s;
  182. {
  183.     register int val;
  184.  
  185.     val = 0;
  186.     while (isdigit(*s))
  187.         val = val * 10 + *s++ - '0';
  188.     if (val > 1900)
  189.         if (setyear++)
  190.             reperror("year");
  191.         else
  192.             year = val;
  193.     else if (*s == '\0')
  194.         if (setday++)
  195.             reperror("day");
  196.         else
  197.             day = val;
  198.     else if (settime++)
  199.         reperror("time");
  200.     else
  201.      {
  202.         hour = val;
  203.         if (*s == ':') {
  204.             s++;
  205.             val = 0;
  206.             while (isdigit(*s))
  207.                 val = val * 10 + *s++ - '0';
  208.             minute = val;
  209.             if (*s == ':') {
  210.                 s++;
  211.                 val = 0;
  212.                 while (isdigit(*s))
  213.                     val = val * 10 + *s++ - '0';
  214.                 second = val;
  215.             } else
  216.                 second = 0;
  217.         } else
  218.             minute = second = 0;
  219.     }
  220.     if (*s)
  221.         words(curarg = s);
  222. }
  223.  
  224.  
  225. static
  226. reperror(s)
  227. char *s;
  228. {
  229.     error("Repeated %s argument: \"%s\"", s, curarg);
  230. }
  231.  
  232.  
  233. /* VARARGS1 */
  234. static
  235. error(s, a1, a2, a3, a4)
  236. char *s;
  237. int a1, a2, a3, a4;
  238. {
  239.     err++;
  240.     if (silent)
  241.         return;
  242.     (void) fprintf(stderr, "Error in time specification: ");
  243.     (void) fprintf(stderr, s, a1, a2, a3, a4);
  244.     (void) fprintf(stderr, "\n");
  245. }
  246.  
  247.  
  248. static
  249. words(s)
  250. char *s;
  251. {
  252.     register struct slist *sp, *found;
  253.     register int size;
  254.     register char *wstart;
  255.  
  256.     sp = slist;
  257.     wstart = s;
  258.     size = 0;
  259.     while (*s && !isdigit(*s))
  260.         size++, s++;
  261.     found = (struct slist *) 0;
  262.     while (*(sp->s_name)) {
  263.         if (sp->s_type <= gtype && CMPN(sp->s_name, wstart, size) ==
  264.             0)
  265.             if (!found) {
  266.                 found = sp;
  267.                 if (strlen(sp->s_name) == size)
  268.                     break;    /* otherwise an abbreviation */
  269.             }
  270.             else
  271.              {
  272.                 error("Ambiguous abbreviation: \"%.*s\"", size,
  273.                      wstart);
  274.                 return;
  275.             }
  276.         sp++;
  277.     }
  278.     if (found)
  279.         (*(found->s_action))(found->s_val);
  280.     else
  281.         error("Unknown word: \"%.*s\"", size, wstart);
  282.     if (*s)
  283.         numbers(curarg = s);
  284. }
  285.  
  286.  
  287. static
  288. timemod(val)
  289. int val;
  290. {
  291.     if (!settime)
  292.         error("Can only use \"am\" or \"pm\" after a time.");
  293.     else if (setmod++)
  294.         reperror("time modifier");
  295.     else if (hour < 12)
  296.         hour += val;
  297.     else if (hour > 12)
  298.         error("Can't use \"am\" or \"pm\" with 24 hour clock.");
  299.     else if (val == 0) /* am && hour == 12 */
  300.         hour = 0;    /* 12am correction */
  301. }
  302.  
  303.  
  304. static
  305. noonmid(val)
  306. int val;
  307. {
  308.     if (val < 0)    /* NOW */ {
  309.         if (settime++)
  310.             reperror("time");
  311.         /* let defaults work */
  312.     } else if (setmod++) /* noon, midnight */
  313.         reperror("time modifier");
  314.     else
  315.      {
  316.         if (!settime)
  317.             settime++;
  318.         else if (hour != 12 || minute != 0 || second != 0)
  319.             error("Illegal time: %02d:%02d:%02d %s", hour, minute,
  320.                  second, curarg);
  321.         hour = val;
  322.         minute = second = 0;
  323.     }
  324. }
  325.  
  326.  
  327. static
  328. daymod()
  329. {
  330.     if (setweek++)
  331.         reperror("\b");
  332.     else if (!setdayofweek)
  333.         error("Can only use \"week\" after a weekday name.");
  334.     else
  335.         dayofweek += 7;
  336. }
  337.  
  338.  
  339. static
  340. weekday(val)
  341. int val;
  342. {
  343.     if (setday++)
  344.         reperror("day");
  345.     else
  346.      {
  347.         setdayofweek++;
  348.         if (val < 7) {
  349.             dayofweek = val - dayofweek;    /* now a displacement */
  350.             if (dayofweek <= 0)
  351.                 dayofweek += 7;
  352.         } else if (val == 7) /* tomorrow */
  353.             dayofweek = 1;
  354.         else    /* today */
  355.             dayofweek = 0;
  356.     }
  357. }
  358.  
  359.  
  360. static
  361. smonth(val)
  362. int val;
  363. {
  364.     if (setmonth++)
  365.         reperror("day of month");
  366.     else
  367.         month = val;
  368. }
  369.  
  370.  
  371. static
  372. checktime()
  373. {
  374.     register int dim;
  375.  
  376.     if (gtype == DAYS && settime)
  377.         error("Times are not accepted.");
  378.     if (year < 1983 || year > 2038)
  379.         error("Year out of range.");
  380.     if (hour > 23 || minute > 59 || second > 59)
  381.         error("Illegal time: %02d:%02d:%02d", hour, minute, second);
  382.     if (!setdayofweek) {
  383.         dim = daysinmonth[month] + (month == 1 ? leapyear(year) : 0);
  384.         if (day > dim)
  385.             error("Month day out of range. (> %d)", dim);
  386.     }
  387.     if (setdayofweek && (setmonth || setyear))
  388.         error("Can't specify a weekday as well as a month or year.");
  389. }
  390.  
  391.  
  392. static
  393. leapyear(y)
  394. int y;
  395. {
  396.     return ((y % 4) == 0 && (y % 100) != 0) || (y % 400 == 0);
  397. }
  398.  
  399.  
  400. static long 
  401. construct()
  402. {
  403.     register int i, days;
  404.  
  405.     adjust();
  406.     days = DAYSTO1983;
  407.     for (i = 1983; i < year; i++)
  408.         days += 365 + leapyear(i);
  409.     for (i = 0; i < month; i++)
  410.         days += daysinmonth[i] + (i == 1 ? leapyear(year) : 0);
  411.     days += day - 1;    /* days since 1 Jan 1970 */
  412.     if (setdayofweek)
  413.         days += dayofweek;
  414.     return days * SECINDAY + hour * SECINHOUR + minute * SECINMIN + second;
  415. }
  416.  
  417.  
  418. static
  419. adjust()
  420. {
  421.     register int dim;
  422.  
  423.     /*
  424.      * make sure time defaults to the future
  425.      */
  426.     if (setdayofweek || setyear || month > tim->tm_mon)
  427.         return;
  428.     if (month < tim->tm_mon) {
  429.         year++;
  430.         return;
  431.     }
  432.     /*
  433.      * month == tim->tm_mon
  434.      */
  435.     if (day > tim->tm_mday)
  436.         return;
  437.     if (day < tim->tm_mday) {
  438.         if (setmonth || ++month / 12)
  439.             year++, month %= 12;
  440.         return;
  441.     }
  442.     /*
  443.      * month == tim->tm_mon && day == tim->tm_mday
  444.      */
  445.     if ((long)(hour*SECINHOUR + minute*SECINMIN + second) <
  446.         (long)(tim->tm_hour*SECINHOUR + tim->tm_min*SECINMIN + tim->tm_sec)) {
  447.         dim = daysinmonth[month] + (month == 1? leapyear(month): 0);
  448.         if (setday || ++day / dim) {
  449.             if (setmonth || ++month / 12)
  450.                 year++, month %= 12;
  451.             day %= dim;
  452.         }
  453.         return;
  454.     }
  455. }
  456.  
  457.  
  458.